﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Design;
using System.IO;
using System.Linq;
using System.Windows.Forms;


namespace Marmat.Forms
{
    [ToolboxItem(true)]
    public partial class FileView : FileManager
    {

        private Dictionary<FileItem, Rectangle> down_rectangleCollection = new Dictionary<FileItem, Rectangle>();
        private Dictionary<FileItem, Rectangle> delete_rectangleCollection = new Dictionary<FileItem, Rectangle>();
        private Dictionary<FileItem, Rectangle> rename_rectangleCollection = new Dictionary<FileItem, Rectangle>();

        public FileView()
        {
            InitializeComponent();
            this.link = new Font(this.Font.Name, this.Font.Size, FontStyle.Underline);
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            if (this.DesignMode && this.BindingField.DataSource is object)
            {
                TextRenderer.DrawText(e.Graphics, this.BindingField.ToString(), this.Font, new Rectangle(0, 0, this.Width, this.Height), this.ForeColor, Color.Transparent, TextFormatFlags.HorizontalCenter | TextFormatFlags.VerticalCenter);
                return;
            }

            this.down_rectangleCollection.Clear();
            this.delete_rectangleCollection.Clear();
            this.rename_rectangleCollection.Clear();
            base.OnPaint(e);
            int top = 0;
            int left;
            int icon_Width = 40;
            int item_Height = 60;
            int down_Width = 40;
            int delete_Width = 40;
            int rename_Width = 40;
            bool m_readOnly = this.IsReadOnly;
            foreach (FileItem item in this.Files)
            {
                left = 1;
                var rect = new Rectangle(left, top - this.VerticalScroll.Value, this.ClientSize.Width - 1, item_Height);
                if (top - this.VerticalScroll.Value < this.Height)
                {
                    // 绘制Icon==================================================
                    var Icon_Rect = new Rectangle(rect.X, top - this.VerticalScroll.Value, icon_Width, item_Height);
                    var icon = FileIconAPI.GetIcon(item.Name);
                    if (icon is object)
                    {
                        int Icon_X = (int)Math.Round((Icon_Rect.Width - icon.Width) / 2d);
                        int Icon_Y = (int)Math.Round((Icon_Rect.Height - icon.Height) / 2d);
                        e.Graphics.DrawIcon(icon, Icon_Rect.X + Icon_X, Icon_Rect.Y + Icon_Y);
                    }

                    // 绘制名称==================================================
                    left = Icon_Rect.Width;
                    var text_Rect = new Rectangle(left, top - this.VerticalScroll.Value, this.ClientSize.Width - left - down_Width - (!m_readOnly ? delete_Width : 0) - (this.ShowRenameCommand ? 40 : 0), item_Height - 10);
                    TextRenderer.DrawText(e.Graphics, item.Name, this.Font, text_Rect, this.ForeColor, Color.Transparent, TextFormatFlags.Left | TextFormatFlags.VerticalCenter);
                    // 绘制文件大小
                    string sizeString = "未知大小";
                    if (item.Size < 1024)
                        sizeString = string.Format("{0:f}", item.Size.ToString()) + " 字节";
                    else if (item.Size < Math.Pow(1024, 2))
                        sizeString = string.Format("{0:f}", item.Size / Math.Pow(1024, 1)) + " KB";
                    else if (item.Size < Math.Pow(1024, 3))
                        sizeString = string.Format("{0:f}", item.Size / Math.Pow(1024, 2)) + " MB";
                    else if (item.Size < Math.Pow(1024, 4))
                        sizeString = string.Format("{0:f}", item.Size / Math.Pow(1024, 3)) + " GB";
                    else if (item.Size < Math.Pow(1024, 5))
                        sizeString = string.Format("{0:f}", item.Size / Math.Pow(1024, 4)) + " TB";
                    else if (item.Size < Math.Pow(1024, 6))
                        sizeString = string.Format("{0:f}", item.Size / Math.Pow(1024, 5)) + " PB";
                    else if (item.Size < Math.Pow(1024, 7))
                        sizeString = string.Format("{0:f}", item.Size / Math.Pow(1024, 6)) + " EB";
                    else if (item.Size < Math.Pow(1024, 8))
                        sizeString = string.Format("{0:f}", item.Size / Math.Pow(1024, 7)) + " ZB";
                    else if (item.Size < Math.Pow(1024, 9))
                        sizeString = string.Format("{0:f}", item.Size / Math.Pow(1024, 8)) + " YB";

                    text_Rect = new Rectangle(text_Rect.Left, top - this.VerticalScroll.Value + 35, text_Rect.Width, 20);
                    TextRenderer.DrawText(e.Graphics, sizeString, this.Font, text_Rect, Color.Gray, Color.Transparent, TextFormatFlags.Left | TextFormatFlags.Top);
                    if (this.Width > 100)
                    {
                        // 绘制下载==================================================
                        left = text_Rect.Right;
                        Rectangle down_Rect;
                        var delete_Rect = default(Rectangle);
                        var rename_Rect = default(Rectangle);
                        down_Rect = new Rectangle(left, top - this.VerticalScroll.Value, down_Width, item_Height);
                        TextRenderer.DrawText(e.Graphics, "下载", this.link, down_Rect, Color.Blue, Color.Transparent, TextFormatFlags.HorizontalCenter | TextFormatFlags.VerticalCenter);
                        left = down_Rect.Right;
                        if (this.ShowRenameCommand)
                        {
                            rename_Rect = new Rectangle(left, top - this.VerticalScroll.Value, rename_Width, item_Height);
                            TextRenderer.DrawText(e.Graphics, "重命名", this.link, rename_Rect, Color.Blue, Color.Transparent, TextFormatFlags.HorizontalCenter | TextFormatFlags.VerticalCenter);
                            left = rename_Rect.Right;
                        }
                        // 绘制删除==================================================
                        if (!m_readOnly)
                        {
                            delete_Rect = new Rectangle(left, top - this.VerticalScroll.Value, delete_Width, item_Height);
                            TextRenderer.DrawText(e.Graphics, "删除", this.link, delete_Rect, Color.Blue, Color.Transparent, TextFormatFlags.HorizontalCenter | TextFormatFlags.VerticalCenter);
                        }
                        // 记录矩形位置
                        this.down_rectangleCollection[item] = down_Rect;
                        this.delete_rectangleCollection[item] = delete_Rect;
                        this.rename_rectangleCollection[item] = rename_Rect;
                    }

                    // 绘制底纹==================================================
                    e.Graphics.DrawLine(Pens.Silver, 0, rect.Bottom, rect.Width, rect.Bottom);
                }
                // 设置变量==================================================
                top += rect.Height;
            }

            // 绘制添加==================================================
            if (!m_readOnly)
            {
                var new_Rect = new Rectangle(icon_Width, top - this.VerticalScroll.Value, this.Width, item_Height);
                TextRenderer.DrawText(e.Graphics, "添加", this.link, new_Rect, Color.Blue, Color.Transparent, TextFormatFlags.Left | TextFormatFlags.VerticalCenter);
                this.new_Rect = new_Rect;
                top += new_Rect.Height;
            }

            this.AutoScrollMinSize = new Size(0, top);
        }

        private Font link;
        private Rectangle new_Rect;

        protected override void OnMouseMove(MouseEventArgs e)
        {
            base.OnMouseMove(e);
            string tag = null;
            Rectangle rect = default;
            var flags = TextFormatFlags.HorizontalCenter | TextFormatFlags.VerticalCenter;
            if (this.new_Rect.Contains(e.Location))
            {
                rect = this.new_Rect;
                tag = "添加";
                flags = TextFormatFlags.Left | TextFormatFlags.VerticalCenter;
            }

            var down_item = this.down_rectangleCollection.FirstOrDefault(x => x.Value.Contains(e.Location));
            var delete_item = this.delete_rectangleCollection.FirstOrDefault(x => x.Value.Contains(e.Location));
            var rename_item = this.rename_rectangleCollection.FirstOrDefault(x => x.Value.Contains(e.Location));
            if (down_item.Key is object)
            {
                rect = down_item.Value;
                tag = "下载";
            }
            else if (rename_item.Key is object)
            {
                rect = rename_item.Value;
                tag = "重命名";
            }
            else if (delete_item.Key is object)
            {
                rect = delete_item.Value;
                tag = "删除";
            }

            if (rect != default && !string.IsNullOrEmpty(tag))
            {
                var size = TextRenderer.MeasureText(tag, this.link, new Size(100, 100), flags);
                int x = (int)Math.Round((rect.Width - size.Width) / 2d);
                int y = (int)Math.Round((rect.Height - size.Height) / 2d);
                var c = new Rectangle(rect.X + x, rect.Y + y, size.Width, size.Height);
                if (flags == (TextFormatFlags.Left | TextFormatFlags.VerticalCenter))
                {
                    c = new Rectangle(rect.X, rect.Y + y, size.Width, size.Height);
                }

                if (c.Contains(e.Location))
                {
                    this.Cursor = Cursors.Hand;
                    return;
                }
            }

            this.Cursor = Cursors.Default;
        }

        protected override void OnMouseClick(MouseEventArgs e)
        {
            base.OnMouseClick(e);
            if (e.Button == MouseButtons.Left)
            {
                string tag = null;
                Rectangle rect = default;
                FileItem fileItem = null;
                var flags = TextFormatFlags.HorizontalCenter | TextFormatFlags.VerticalCenter;
                var down_item = this.down_rectangleCollection.FirstOrDefault(x => x.Value.Contains(e.Location));
                var delete_item = this.delete_rectangleCollection.FirstOrDefault(x => x.Value.Contains(e.Location));
                var rename_item = this.rename_rectangleCollection.FirstOrDefault(x => x.Value.Contains(e.Location));
                if (down_item.Key is object)
                {
                    fileItem = down_item.Key;
                    rect = down_item.Value;
                    tag = "下载";
                }
                else if (rename_item.Key is object)
                {
                    fileItem = rename_item.Key;
                    rect = rename_item.Value;
                    tag = "重命名";
                }
                else if (delete_item.Key is object)
                {
                    fileItem = delete_item.Key;
                    rect = delete_item.Value;
                    tag = "删除";
                }

                if (tag is null && this.new_Rect.Contains(e.Location))
                {
                    rect = this.new_Rect;
                    tag = "添加";
                    flags = TextFormatFlags.Left | TextFormatFlags.VerticalCenter;
                }

                if (rect != default && !string.IsNullOrEmpty(tag))
                {
                    var size = TextRenderer.MeasureText(tag, this.link, new Size(100, 100), flags);
                    int x = (int)Math.Round((rect.Width - size.Width) / 2d);
                    int y = (int)Math.Round((rect.Height - size.Height) / 2d);
                    var c = new Rectangle(rect.X + x, rect.Y + y, size.Width, size.Height);
                    if (flags == (TextFormatFlags.Left | TextFormatFlags.VerticalCenter))
                    {
                        c = new Rectangle(rect.X, rect.Y + y, size.Width, size.Height);
                    }

                    if (c.Contains(e.Location))
                    {
                        switch (tag ?? "")
                        {
                            case "下载":
                                {
                                    var args = new FileItemEventArgs(fileItem);
                                    DownloadItemClick?.Invoke(this, args);
                                    break;
                                }

                            case "删除":
                                {
                                    this.Files.Remove(fileItem);
                                    break;
                                }

                            case "重命名":
                                {
                                    var info = new System.IO.FileInfo(fileItem.Name);
                                    string fileName = System.IO.Path.GetFileNameWithoutExtension(info.Name);
                                    if (InputValue.Show(ref fileName, "重命名", "请输入文件的新文件名:"))
                                    {
                                        fileItem.Name = fileName + info.Extension;
                                        this.SetValue();
                                        if (this.BindingField.IsBinding)
                                        {
                                            this.BindingField.WriteValue();
                                        }

                                        this.Invalidate();
                                    }

                                    break;
                                }

                            case "添加":
                                {
                                    var dialog = new OpenFileDialog();
                                    dialog.Multiselect = this.MultiAddImage;
                                    dialog.Filter = this.Filter;  // 设置筛选器
                                    if (dialog.ShowDialog() == DialogResult.OK)
                                    {
                                        foreach (string fileName in dialog.FileNames)
                                        {
                                            var info = new FileInfo(fileName);
                                            var item = new FileItem()
                                            {
                                                Id = this.BuildFileID(fileName),
                                                Name = info.Name,
                                                Size = info.Length,
                                                LocalPath = fileName
                                            };
                                            this.Files.Add(item);
                                            if (this.BindingField.IsBinding)
                                            {
                                                this.BindingField.WriteValue();
                                            }
                                        }
                                    }

                                    break;
                                }
                        }
                    }
                }
            }
        }

        protected override void NotifyPropertyChanged()
        {
            this.Invalidate();
        }
    }
}